/**
 * @author James Simpson
 */
//TODO: Add a Request Timeout and Handler
var twtrAPI = {
	T: null,
	token: null,
	apiURL: "https://api.twitter.com/1/",
//JSON describing the API urls for twitter requests, for automated formation based on request data + these objects
	urls: {	"user": 	{str1: "statuses/user_timeline.json?callback=?" },
			"public": 	{str1: "statuses/public_timeline.json?callback=?"},
			"lists": 	{user : null, str1: "/lists.json?callback=?"},
			"subs": 	{str1: "lists/subscriptions.json?callback=?"},	
			"trends": 	{str1: "trends/", woeid: null, str2: ".json?callback=?"},
			"replies":	{str1: "related_results/show/", statusID: null, str2: ".json"},
			"data": 	{str1: "users/show.json?callback=?"},						//TODO: What is this?
			"friends":	{str1: "statuses/friends.json?callback=?"},
			"follows":	{str1: "statuses/followers.json?callback=?"},
			"search":	{str1: "http://search.twitter.com/search.json?callback=?"},
			"public": 	{str1: "statuses/public_timeline.json?callback=?"},
			"user-list":{user: null, str1: "/lists/", list: null, str2: "/statuses.json?callback=?"},
//Auth User Timelines
			"home":		{str1: "statuses/home_timeline.json?callback=?"},
			"mentions":	{str1: "statuses/mentions.json?callback=?"},
			"rtByMe":	{str1: "statuses/retweeted_by_me.json?callback=?"},
			"rtToMe":	{str1: "statuses/retweeted_to_me.json?callback=?"},
			"rtOfMe":	{str1: "statuses/retweeted_of_me.json?callback=?"}
		},
	init: function(T){
		this.T = T;
		//this.token = twttr.anywhere.token.replace("+", "%2B")
		//this.token = this.token.replace("=", "%3D");
	},
	requestUrl: function(data){
		var url = twtrAPI.urls[data.request];
		var strURL = "";
		
		if(data.request != "search"){
			strURL = twtrAPI.apiURL;
		}
		if (url) {
			for (param in url) { //if data has param, set the value in url
				if (data[param]) {
					url[param] = data[param];
				}
			}
			for (piece in url) { //chain together each piece of url to form the needed url
				strURL += url[piece];
			}
			return strURL;
		}
	},
	getAuthUser: function() {
		return twtrAPI.T.currentUser;
	},
//Available Trend IDs: http://api.twitter.com/1/trends/available.json
//Retrieve Trends by ID: http://api.twitter.com/1/trends/:woeid.format
	getUserRes: function(data, callback){
		var strURL = this.apiURL;
		//var qs = {user_id: data.user_id};
        
		switch(data.request){
			case "lists": 	strURL += data.user +  "/lists.json?callback=?";							
							break;
							
			case "subs": 	strURL += "lists/subscriptions.json?callback=?";							
							break;
											
			case "trends": 	strURL += "trends/" + data.woeid + ".json?callback=?";
							break;
			case "data": 	strURL += "users/show.json?callback=?";
							break;
								
			case "friends":	strURL += "statuses/friends.json?callback=?";
							break;

			case "follows":	strURL += "statuses/followers.json?callback=?";
							break;
		}
		$.getJSON(strURL, data.qs, callback);
    },
	getAuthUserRes: function(data, callback){
		var user = this.getAuthUser();
		
		switch (data.request) {
			case "searches": callback(user.savedSearches(data.qs));
				break;
		}
	},
//Status Replies: https://api.twitter.com/1/related_results/show/<Status ID>.json
	getPubTmln: function (data, cb) {
		var strURL = this.apiURL;
		strURL = twtrAPI.requestUrl(data);
				
		switch(data.request){
			case "user": 		data.qs.screen_name = data.user;
						 		break;
		}
		this.setTmlnQS(data);
//TODO: get this working, the 2nd and 3rd pieces delimited as below change on each request it seems
//it looks like that is required, but how do I reverse engineer that or what is the method to automate it
//twttr.anywhere._settoken();
data.qs.oauth_access_token = this.token;
		$.getJSON(strURL, data.qs, cb);

/* $.ajax({'success': cb.success, 'error': cb.error, 'complete': cb.complete, 
 			'beforeSend': cb.beforeSend, 'timeout': cb.timeout,
 			'type': 'GET', 'url': strURL,'data': data.qs,'dataType':'json'});
*/
	},
	getAuthUserTmln: function(data, callback){
		var strURL = this.apiURL;
        var user = this.getAuthUser();
		var json;
		this.setTmlnQS(data);
//TODO: No results on max_id request needs to remove the scroll event
//TODO: How the hell do I hook into these events finishing so I can toggle UI element settings?
		switch (data.request) {
			case "home":
				var home = user.homeTimeline(data.qs);
				home.each(callback);
				break;
			case "mentions":
				user.mentions(data.qs).each(callback);
				break;
			case "rtByMe":
				strURL += "statuses/retweeted_by_me.json?callback=?";
				user.retweeting(data.qs).each(callback);
				break;
			case "rtToMe":
				strURL += "statuses/retweeted_to_me.json?callback=?";
				user.retweets(data.qs).each(callback);
				break;
			case "rtOfMe":
				strURL += "statuses/retweeted_of_me.json?callback=?";
				user.retweeted(data.qs).each(callback);
				break;
		}
		tmlnManager.toggleLoading();
		//$.getJSON(strURL, data.qs, callback);
	},
	setTmlnQS: function(data){
//TODO: Search request QS is completely different, need something kind of custom I guess: http://dev.twitter.com/doc/get/search
//TODO: How do I determine which QS parameters to set
//QS Params: since_id,max_id,count,page,trim_user,include_entities
		data.qs.include_entities = "1";  //always
		data.qs.count = 100;	//number of tweets to get
		data.qs.per_page = 100; //some timelines use this for number of tweets instead, wtg twitter
		
		if(data.rqType == "since_id"){
				data.qs.since_id = $("#" + data.cont + " .twtr-tweet:first").attr("data-item-id");
			}
		else if(data.rqType == "max_id"){
				data.qs.max_id = $("#" + data.cont + " .twtr-tweet:last").attr("data-item-id");
		}

	},
//Start Tweet Actions
	favorite: function(tweetID){
		this.T.Status.favorite(tweetID);
	},
	unfavorite: function(tweetID) {
		this.T.Status.unfavorite(tweetID);
	},
	retweet: function(tweetID){
		this.T.Status.retweet(tweetID);
	},
	reply: function(message, tweetID){
		this.T.Status.find(tweetID).reply(message);
	},
	remove: function(tweetID){
		this.T.Status.find(tweetID).destroy();
	},
	tweet: function(message) {
		this.T.Status.update(message);
	},
//End Tweet Actions
//Start User Actions
	followUser: function(userID){
		this.T.User.find(userID).follow();
	},
	unfollowUser: function(userID){
		this.T.User.find(userID).unfollow();
	},
	addToListUser: function(userID){
		this.T.List.add(userID);
	},
	delFromListUser: function(userID){
		this.T.List.remove(userID);
	},
	blockUser: function(userID){
		this.T.User.find(userID).block();
	},
	unblockUser: function(userID){
		this.T.User.find(userID).unblock();
	},
	directMessage: function(message, userID){
		this.T.User.find(userID).directMessage(message);
	},
//End User Actions
//Start List Actions
	createList: function(){
		
	},
	deleteList: function(){
		
	},
	subscribeList: function(){
		
	},
	unfollowList: function(){
		
	}
//End List Actions
}
function metweTimeline(data){
	this.data = data;
	var This = this;

	this.get = function() //retrieve a timeline
	{
		tmlnManager.toggleLoading();
		//twtrAPI.request(this.data, this.anyCallback); //Change to this once data conversion is done
		//	var qs = {include_entities:1, per_page: 100, include_rts:1};
//TODO: Add a search request callback, it's a completely different data set
var callbacks = {success: null, error: This.error, complete: This.complete, beforeSend: This.beforeSend, timeout: This.timeout };
		if (this.data.tmln == "auth") {
			twtrAPI.getAuthUserTmln(this.data, this.anyCallback);
		}
		else if(this.data.request == "search"){
			callbacks.success = This.searchCallback;
			twtrAPI.getPubTmln(this.data, callbacks.success);
		}
		else {
			callbacks.success = This.callback;
			twtrAPI.getPubTmln(this.data, callbacks.success);
		}
	}
	this.anyCallback = function(tweet){
		This.addTweet(This.buildTweet(tweet));
		This.setNewMarker();
	}
	this.searchCallback = function(json) {
		This.callback(json.results);
	}
//TODO: embed the original tweet on retweets; retweeted_status: present when a retweet
	this.callback = function(json, textStatus, jqXHR) //callback processor
	{
//TODO: No results on max_id request needs to remove the scroll event
		var i = 0;
		
		if (This.data.rqType == "since_id") { //Old tmln, new posts insert before first tweet
			for (var status in json) {
				This.addTweet(This.buildTweet(json[status]));
			}			
		}
		else { //new tmln or infinite scroll, append
			if(This.data.rqType == "max_id") {
				i=1;
			}
			for (i; i < json.length; i++) {
				This.addTweet(This.buildTweet(json[i]));
			}			
		}
		This.complete();	
	}
	this.error = function(xhr, msg, exc){
		//An error occurred requesting the timeline
	}
	this.complete = function(xhr, msg){ //timeline request and processing complete
		This.setNewMarker();
		This.applyToggles();		
	}
	this.beforeSend = function(xhr) { //do stuff necessary prior to the request
		//TODO: set authorization header I guess, that should be in the API object though
		//Display the Loading thing and do other stuff?
//		xhr.setRequestHeader("Authorization", "OAUTH oauth_access_token=" + twtrAPI.token);
//		xhr.setRequestHeader("Access-Control-Allow-Origin", "http://metwe.jsblogstop.com");
		This.applyToggles();
	}
	this.timeout = function () { //timeline request timed out
		
	}
	this.setNewMarker = function() {
		$("#tmln-new-marker").show();
		if(This.data.rqType == "since_id") {
			$("#tmln-new-marker").insertBefore("#" + This.data.cont + This.data.qs.since_id);
			$("#tmln-new-marker").text("New Tweets Above");
		}
		else if(This.data.rqType == "max_id") {
			$("#tmln-new-marker").insertAfter("#" + This.data.cont + This.data.qs.max_id);
			$("#tmln-new-marker").text("Old Tweets Below");
		}
		else {
			$("#tmln-new-marker").hide();
		}
	}
	this.applyToggles = function() {
		if(this.data.rqType == "max_id"){
			tmlnManager.scrollToggle();
		}
		tmlnManager.toggleLoading();
	}
	this.buildTweet = function(status) {		
		var $Tweet;
		
		if(this.data.tmln == "auth"){//decide if it's an Anywhere or my own API request
			$Tweet = twtrTweet.build(status, this.data.cont);
		}
		else {
			$Tweet = twtrTweet.build(status, this.data.cont);
		}
		return $Tweet;
	}
	this.addTweet = function(tweet){
		//TODO:Replaces Show Status and used for all Tweets
		if (This.data.rqType == "since_id") { //Old tmln, insertBefore first tweet
			tweet.insertBefore("#" + this.data.cont + this.data.qs.since_id);
		}
		else { //new tmln or infinite scroll, append
			$("#" + this.data.cont).append(tweet);
		}
	}
	this.setActions = function() {
		$("#" + this.data.cont + " .tweet-favorite").click(twtrTweet.favorite);
        $("#" + this.data.cont + " .tweet-retweet").click(twtrTweet.retweet);
 		$("#" + this.data.cont + " .tweet-reply").click(twtrTweet.reply);
	}
}
var authUser = {
	user: null,
	init: function() {
		this.user = twtrAPI.getAuthUser();
		userManager.buildAuthUser();
		authUser.getLists();
		authUser.getSubs();
		authUser.getTrends();
	},
	getLists: function(){
		var data = {user: this.user.screenName, request: "lists"};
		data.qs = {};
		twtrAPI.getUserRes(data, this.processLists);
	},
	getSubs: function() {
		var data = {user: this.user.screenName, request: "subs"};
		data.qs = {screen_name: this.user.screenName};
		twtrAPI.getUserRes(data, this.processSubs);
	},
//TODO: Make a generic list processor
	processLists: function(json, textStatus, jqXHR){
		var userLists = "#page-lists-" + authUser.user.screenName;
		$(userLists).html("<ul id='lists-" + authUser.user.screenName + "'></ul>");

		for(var i = 0; json.lists.length > i; i++){		
			$(userLists + " ul").append("<li><span data-twi-user=\"" + json.lists[i].user.screen_name + "\" data-twi-list=\"" + json.lists[i].slug + "\">" + json.lists[i].name + "</span></li>");
		}
		//$(userLists + " .list-expand").click(slideTmlnList);
		$(userLists + " span").click(tmlnManager.loadList);
	},
	processSubs: function(json, textStatus, jqXHR){
		//Temporary for testing, need to make this generic for all list requests somewhere
		var userLists = "#page-subs-" + authUser.user.screenName;
		//$(userLists).html("<h2>Subscriptions<div class='list-expand' expand-id='lists-" + authUser.user.screenName + "-subs'>+/-</div></h2><ul id='lists-" + authUser.user.screenName + "'></ul>");
		$(userLists).html("<ul id='subs-" + authUser.user.screenName + "'></ul>");
		for(var i = 0; json.lists.length > i; i++){		
			$(userLists + " ul").append("<li><span data-twi-user=\"" + json.lists[i].user.screen_name + "\" data-twi-list=\"" + json.lists[i].slug + "\">" + json.lists[i].name + "</span></li>");
		}
		//$(userLists + " .list-expand").click(slideTmlnList);
		$(userLists + " span").click(tmlnManager.loadList);
	},
	getSearches: function() {
		var data = {user: this.user.screenName, request: "searches"};
		data.qs = {};
		twtrAPI.getUserRes(data, this.processSearches);
	},
	processSearches: function(json){
		//TODO: This completely does not work yet, since this is an @anywhere request
		var userSearches = "#metwe-searches-" + authUser.user.screenName;
		$(userSearches).html("<h2>Saved Searches<div class='list-expand' expand-id='lists-" + authUser.user.screenName + "'>+/-</div></h2><ul id='lists-" + authUser.user.screenName + "'></ul>");
		for(var i = 0; json.savedSearch.length > i; i++){		
			$(userLists + " ul").append("<li data-query='" + json.savedSearch[i].query + "'>" + json.savedSearch[i].name + "</li>");
		}
		$(userLists + " .list-expand").click(slideTmlnList);
		$(userLists + " li").click(authUser.loadSearch);
	},
	processSearch: function(savedSearch){
		
	},
	getTrends: function(){
		var data = {woeid: 1, request: "trends"};
		data.qs = {};
		twtrAPI.getUserRes(data, this.processTrends);		
	},
	processTrends: function(json){
		var userTrends = "#page-trends";

		$(userTrends).html("<ul id='trends-" + authUser.user.screenName + "'></ul>");
		for(var i = 0; json[0].trends.length > i; i++){		
			$(userTrends + " ul").append("<li><span data-query='" + json[0].trends[i].query + "'>" + json[0].trends[i].name + "</span></li>");
		}
		$(userTrends + " span").click(tmlnManager.loadSearch);
	},
	loadSearch: function (){
		
	},
// data = { tmln: public/auth; request: user/user-list;home/mentions/rtByMe/rtToMe/rtOfMe, rqType:new/since_id/max_id user: James_GAF,
// list: list-name/null, qs{} }
	getHome: function(){
		tmlnManager.request(this.getTmlnDataDefault("home"));
	},
	getOwnTweets: function() {
		var data = {tmln: "public", request: "user", user: this.user.screenName};
		data.qs = {};
		tmlnManager.request(data);
	},
	getMentions: function(){
		tmlnManager.request(this.getTmlnDataDefault("mentions"));		
	},
	getRtToMe: function(){
		tmlnManager.request(this.getTmlnDataDefault("rtToMe"));		
	},
	getRtByMe: function(){
		tmlnManager.request(this.getTmlnDataDefault("rtByMe"));		
	},
	getRtOfMe: function(){
		tmlnManager.request(this.getTmlnDataDefault("rtOfMe"));		
	},
	getTmlnDataDefault: function(strRequest) {
		var data = {tmln: "auth", request: strRequest, user: this.user.screenName};
		data.qs = {};
		return data;
	}
}
function loadList(){
	//placeholder
}
function slideTmlnList() {
	//placeholder
}
function tabSwitch() {
//Inactive current active tab/page
	var $actTab = $(".tabs-cont .active-tab")
	$actTab.toggleClass("active-tab inactive-tab");
	$actTab.click(tabSwitch);
	var $actPage = $(".tabs-pages .active-page");
	$actPage.toggleClass("active-page inactive-page");
//	$actPage.hide();

//Active tab/page selected
	var $tab = $(this);
	$tab.toggleClass("active-tab inactive-tab");
	$tab.unbind();
	var $page = $("#" + $tab.attr("data-page-id"));
	$page.toggleClass("active-page inactive-page");
	//$page.slideToggle();
}
var userManager = {
	buildAuthUser: function (){
		var user = twtrAPI.T.currentUser;
		var html = "<section class='metwe-profile-left metwe-profile' id='metwe-profile-" + user.screenName + "'>";
		html += "<span class='left-profile-image'>"; // style='float: left; padding-right: 5px;
		html += "<img src='" + user.profileImageUrl + "'/></span>";
		html += "<div class='auth-profile-name'><span class='metwe-action' onclick='authUser.getOwnTweets();'>" 
				+ user.screenName + " " + user.statusesCount + "</span></div>";
		html += "<div style='clear: both;'/>"
					+ "<section class='cached-timelines'>"
						+ "<section class='cached-tmln' id='metwe-user-timelines' user-id='" + user.screenName + "'>"
							+ "<h2>Your Timelines</h2>"
							+ "<ul>"
								+ "<li onclick='authUser.getHome();'>Home</li>"
								//+ "<li onclick='authUser.getOwnTweets();'>Your Tweets</li>"
								+ "<li onclick='authUser.getMentions();'>@ Mentions</li>"
					        + "</ul>"
							+ "<section class='auth-retweet-tmlns'>"
								+ "<h2>Retweets</h2>"
								+ "<ul id='retweets-list'>"
									+ "<li onclick='authUser.getRtToMe();'>to You</li>"
									+ "<li onclick='authUser.getRtByMe();'>by Me</li>"
									+ "<li onclick='authUser.getRtOfMe();'>of You</li>"
								+ "</ul>"
        					+ "</section>"									
						+ "</section>"
				+ "</section>"			
			+ "</section>"
			+ "<section>"
				+ "<div class='tabs-cont' id='list-tabs-" + user.screenName + "'>"
					+ "<span class='metwe-tab active-tab' data-page-id='page-lists-" + user.screenName + "'>Lists</span>"
					+ "<span class='metwe-tab inactive-tab' data-page-id='page-subs-" + user.screenName + "'>Subs</span>"
					+ "<span class='metwe-tab inactive-tab' data-page-id='page-searches-" + user.screenName + "'>Searches</span>"
					+ "<span class='metwe-tab inactive-tab' data-page-id='page-trends'>Trends</span>"
				+ "</div>"
				+ "<div class='tabs-pages'>"
					+ "<div class='metwe-user-list active-page' id='page-lists-" + user.screenName + "'/>"
					+ "<div class='metwe-user-list inactive-page' id='page-subs-" + user.screenName + "'/>"
					+ "<div class='metwe-user-list inactive-page' id='page-searches-" + user.screenName + "'/>"
					+ "<div class='metwe-user-list inactive-page' id='page-trends'/>"
				+ "</div>"
			+ "</section>" 
		+ "";
		$("#metwe-column-left .metwe-column-inner").append(html);
		$(".metwe-tab").click(tabSwitch);
	}
}
var tmlnManager = {
	activeTmln: "",
	tmlnCont: "#metwe-timeline-container",
	tmlnPrefix: "metwe-timeline-",
	request: function (data) {
//TODO: data redesign.. { auth: true/false, request: tmln/user/userStatuses/userList/status/statusAction,
// resource: home/mentions/rtByMe/rtToMe/rtOfMe|user; UserRes?;retweet/unretweet/favorite/unfavorite/reply;

// data = { tmln: public/auth; request: user/user-list;home/mentions/rtByMe/rtToMe/rtOfMe, rqType:new/since_id/max_id user: James_GAF,
// list: list-name/null, qs{} }
//TODO: Need a Queuing system
		this.manageTmln(data);		
		var tmlnRequest = new metweTimeline(data);
		tmlnRequest.get();
	},
	update: function() {
//TODO: Implement tmln refresh for the clicked Header tmln-link
alert("Not Yet Implemented");
	},
	loadSearch: function(query) {
		var data = {tmln: "public", request: "search"};
		data.qs = {q: $(this).attr("data-query")};
		tmlnManager.request(data);		
	},
	loadList: function() {
		var data = {tmln: "public", request: "user-list", user: $(this).attr("data-twi-user"), list: $(this).attr("data-twi-list")};
		data.qs = {};
		tmlnManager.request(data);
	},
//TODO: Merge setCont and setHeader, possibly make a generic naming convention for new tmln
	setCont: function(data) {
		if(data.tmln == "auth"){
			data.cont = data.user + "-" + data.request;
		}
		else {
			switch(data.request) {
			case "user":
				data.cont = data.user;				
				break;
			case "user-list":
				data.cont = data.user + "-" + data.list;
				break;
			}
		}
		data.cont = this.tmlnPrefix + data.cont;
	},
	setHeader: function(data) {
		var $TmlnHead = $("<h2>Viewing Timeline: </h2>");
		var $TmlnLink = $("<span title='Refresh' class='tmln-link'></span>");
		
		switch(data.request) {
			case "public": $TmlnLink.text("Recent Tweets");
				break;
			case "search": $TmlnHead.text("Search Results for ");
				$TmlnLink.text(data.qs.q);
				break;
			case "home": $TmlnLink.text("Home");
				break;
			case "rtByMe": $TmlnLink.text(data.user + " Retweets");
				break;
			case "rtOfMe": $TmlnLink.text(data.user + " Retweeted");
				break;
			case "rtToMe": $TmlnLink.text("Following Retweets");
				break;
			case "mentions": $TmlnLink.text(data.user + " Mentions");
				break;
			case "user": $TmlnLink.text(data.user);
				break;
			case "user-list": $TmlnLink.text("@" + data.user + "/" + data.list);
				break;
		}
		$TmlnLink.data(data.cont);
		$TmlnLink.click(tmlnManager.update);

		$TmlnHead.append($TmlnLink);
		$TmlnHead.attr("id", data.cont + "-header");
		$("#metwe-menu-bar").append($TmlnHead);
	},
	manageTmln: function(data){
		this.setCont(data);

//Set the request type based on container existing or not. Infinite Scroll sets itself, I guess?
		if ($("#" + data.cont).length <= 0) {
			var $Tmln = $("<div class='metwe-timeline' id=\"" + data.cont + "\"></div>");
			this.setHeader(data);
			$Tmln.data(data);			
			$(this.tmlnCont).append($Tmln);
			data.rqType = "new";
		}
		else if(data.rqType != "max_id"){
			data.rqType = "since_id";
		}
		
//Show the appropriate timeline
		if(this.activeTmln != "") {
			$("#" + this.activeTmln).hide();
			$("#" + this.activeTmln + "-header").hide();
		}
		this.activeTmln = data.cont;
		this.updateTimestamps();
		$("#" + this.activeTmln).show();
		$("#" + this.activeTmln + "-header").show();
	},
	updateTimestamps: function() {
		$("#" + this.activeTmln + " .tweet-timestamp").each(twtrTweet.updateTimestamp);
	},
	toggleLoading: function (){
//Show or hide the Loading Animation, TODO: make a loading animation
		$(".metwe-loading").toggle();
	},
	scrollToggle: function() {
		if($("#metwe-timeline-container").data("events") != undefined){
			$("#metwe-timeline-container").unbind("scroll");
		}
		else {
			$("#metwe-timeline-container").scroll(tmlnManager.infiniteScroll);
		}				
	},
	infiniteScroll: function() {
		var E = $(this).data("events");
		if(this.scrollHeight - this.offsetHeight - $(this).scrollTop() < 500){
			//this works on the Container, so activeTmln is the one to fetch for.
			tmlnManager.scrollToggle(); //unbind the scroll until the fetch is done
			tmlnManager.fetchScroll();
		}
	},
	fetchScroll: function() {
		var data = $("#" + this.activeTmln).data();
		data.rqType = "max_id";
		var tmlnRequest = new metweTimeline(data);
		tmlnRequest.get();
		
		//tmlnManager.scrollToggle();//PH for testing only
	}
}
var tweetBox = {
	$box: null,
	$button: null,
	$count: null,
	init: function() {
		this.$box 		= $("#tweet-box");
		this.$button 	= $("#metwe-tweet-button");
		this.$count 	= $("#tweet-count");
		this.setTweet();
	},
	setReply: function(replyID, userReply) {
		tweetBox.$box.attr("data-reply-id", replyID)
		tweetBox.$box.val("@" + userReply);
		tweetBox.$button.unbind();
		tweetBox.$button.click(tweetBox.reply);
	},
	setTweet: function(){
		tweetBox.$button.unbind();
		tweetBox.$button.click(tweetBox.tweet);
	},
	tweet: function() {
		twtrAPI.tweet(tweetBox.$box.val());
		tweetBox.reset();
	},
	reply: function(){
		twtrAPI.reply(tweetBox.$box.val(), tweetBox.$box.attr("data-reply-id"));		
		tweetBox.reset();
		tweetBox.setTweet();
	},
	reset: function() {
		tweetBox.$box.val("");
		this.$count.text("140");
	}
}
String.prototype.dashToCamel = function(){
	return this.replace(/(\_[a-z])/g, function($1){return $1.toUpperCase().replace('_','');});
}

var twtrTweet = {
	updateTimestamp: function () {
		$(this).text(twtrTweet.timeAgo($(this).attr("data-timestamp")));
	},
	camelData: function(object){
		for(var prop in object){
			if (typeof(object[prop])=="object") {//recursively traverse down tree
                twtrTweet.camelData(object[prop]);
        	}
			object[prop.dashToCamel()] = object[prop];
			//delete object[prop]; How do I know when this is needed or is it at all?
		}
	},
	build: function (jsonTweet, cont) {
//TODO: Search result data contains no User Object, instead it has properties with names different than typical.
//I need to scrub the requried data into a user object I guess
		if(jsonTweet.idStr == undefined){ //only scrub if required
			twtrTweet.camelData(jsonTweet);			
		}

	   	var htmlUserLink = "<a target='_blank' class='userLink' alt='Profile Pic' rel='nofollow' href='http://www.twitter.com/" + jsonTweet.user.screenName + "'>";
       	var html = "";
	   
	   	if(jsonTweet.entities.urls.length > 0) {//tag tweets with links
         	html += "<div class='twtr-tweet linked-tweet'>";
       	}
	   	else {
	   	 	html += "<div class='twtr-tweet unlinked-tweet'>";
       	}
 
	   	html += "<div class='twtr-tweet-wrap'>"
				+ "<div class='twtr-avatar'>"
                    + "<div class='twtr-img'>" + htmlUserLink + "<img src='" + jsonTweet.user.profileImageUrl + "'/></a></div>"
						+ "</div>"
					+ "</div>"
                + "<div class='twtr-tweet-text'>"
                  + "<div class='tweet-row'>"
                    + htmlUserLink + jsonTweet.user.screenName + "</a> " + jsonTweet.user.name
					+ "<div class='user-actions' data-item-id='" + jsonTweet.idStr + "' data-tweet-id='" + cont + jsonTweet.idStr + "'/>"
				  + "</div>"
                  + this.formatTweet(jsonTweet)
                + "</div>"
				+ "<span class='tweet-timestamp' data-timestamp='" + jsonTweet.createdAt + "'>" + this.timeAgo(jsonTweet.createdAt) + "</span>"
				+ "<span class='tweet-actions' data-item-id='" + jsonTweet.idStr + "' data-tweet-id='" + cont + jsonTweet.idStr + "'/>"
				+ "<div style='clear: both;'/>"
              + "</div>";
			  
		var $Tweet = $(html);

		$Tweet.attr("id", cont + jsonTweet.idStr); //really big unique ID, because tweets can appear in multiple timelines
		$Tweet.attr("data-item-id", jsonTweet.idStr);
		$Tweet.attr("data-user-id", jsonTweet.user.screenName);
		$Tweet.attr("data-user-name", jsonTweet.user.name);
		$Tweet.attr("data-profile-img", jsonTweet.user.profileImageUrl);
		
//Change Actions based on if tweet from Current User
		if(twtrAPI.T.currentUser.screenName != jsonTweet.user.screenName){
			$Tweet = this.addUserActions($Tweet, jsonTweet);
			$Tweet = this.addTweetActions($Tweet, jsonTweet, false);
		}
		else {
			$Tweet = this.addTweetActions($Tweet, jsonTweet, true);
		}
		
		return $Tweet;
	},
	addUserActions: function($Tweet, jsonTweet){
		
		var $Corner = $Tweet.find(".user-actions");
		
		if(jsonTweet.user.following == false){
			alert("Not FOllowing");
		}
		this.buildUserAction($Corner, jsonTweet.user.following, "Follow"); //Does not work unauth
//Does not work unauth		this.buildUserAction($Corner, false, "Block");
		this.buildUserAction($Corner, false, "Message");
		this.buildUserAction($Corner, false, "List");

		return $Tweet;
	},
	addTweetActions: function($Tweet, jsonTweet, isAuth){
		var $Actions = $Tweet.find(".tweet-actions");
		
		if(isAuth){
			this.buildAction($Actions, false, "Remove");	
		}
		else {
			this.buildAction($Actions, false, "Reply");
			this.buildAction($Actions, jsonTweet.retweeted, "Retweet");
			this.buildAction($Actions, jsonTweet.favorited, "Favorite");
		}

		return $Tweet;
	},
	buildUserAction: function($Actions, acted, text){
		var $DefaultAction = $("<span><span class='sprite'></span></span>");
		var $Action = $DefaultAction.clone();
		var strClick = "";
		
		$Action.addClass("user-" + text.toLowerCase());
		if(acted){
			$Action.find(".sprite").toggleClass("sprite active-sprite");			
			$Action.attr("title", "Undo " + text);
			strClick += "un";
		}
		else{
			$Action.attr("title", text);
		}
		strClick += text.toLowerCase();
		$Action.click(twtrTweet[strClick]);
		$Actions.append($Action);
	},
	buildAction: function($Actions, acted, text){
		var $DefaultAction = $("<span><span class='sprite'></span></span>");
		var $Action = $DefaultAction.clone();
		var strClick = ""; //"twtrTweet.";
		
		$Action.addClass("tweet-" + text.toLowerCase());
		if(acted){
			$Action.find(".sprite").toggleClass("sprite active-sprite");			
			$Action.append("Undo " + text);
			strClick += "un";
		}
		else{
			$Action.append(text);
		}
		strClick += text.toLowerCase();
		$Action.click(twtrTweet[strClick]); //TODO: This is not working :(
		$Actions.append($Action);
	},
	follow: function() {
		
	},
	unfollow: function() {
		
	},
	block: function() {
		
	},
	unblock: function() {
		
	},
	message: function() {
		
	},
	favorite: function(){
		alert("Favorite " + $(this).parent().attr("data-item-id"));
		twtrAPI.favorite($(this).parent().attr("data-item-id"));
		twtrTweet.actionUpdate(this, "active-sprite", "Unfavorite", twtrTweet.unfavorite);
	},
	unfavorite: function() {
		alert("Unfavorite " + $(this).parent().attr("data-item-id"));
		twtrAPI.unfavorite($(this).parent().attr("data-item-id"));
		twtrTweet.actionUpdate(this, "sprite", "Favorite", twtrTweet.favorite);
	},
	retweet: function(){
		alert("Retweeting " + $(this).parent().attr("data-item-id"));
		twtrAPI.retweet($(this).parent().attr("data-item-id"));
		twtrTweet.actionUpdate(this, "active-sprite", "Undo Retweet", twtrTweet.unretweet);
	},
	unretweet: function(){
		alert("Remove Retweet of " + $(this).parent().attr("data-item-id"));
		twtrAPI.remove($(this).parent().attr("data-item-id"));
		twtrTweet.actionUpdate(this, "sprite", "Retweet", twtrTweet.retweet);
	},
	actionUpdate: function(action, sprite, text, handler){
		$(action).unbind();
		$(action).html("<span class='" + sprite + "'></span>" + text);
		$(action).click(handler);
	},	
	reply: function(){
		var replyID = $(this).parent().attr("data-item-id");
		var userReply = $("#" + $(this).parent().attr("data-tweet-id")).attr("data-user-id");
		tweetBox.setReply(replyID, userReply);
	},
	deleteTweet: function(){
		
	},
	timeAgo: function(dateString) { 
//TODO: This ripped Code is so ugly, clean this shit up
      	var rightNow = new Date();
      	var then = new Date(dateString);
		var strTimeAgo = "";
	    then = Date.parse(dateString.replace(/( \+)/, ' UTC$1'));

      var diff = rightNow - then;

      var second = 1000,
          minute = second * 60,
          hour = minute * 60,
          day = hour * 24,
          week = day * 7;

      if (isNaN(diff) || diff < 0) {
        strTimeAgo = ""; // return blank string if unknown
      }
	  else if (diff < second * 2) {
        strTimeAgo = "right now";
      }
      else if (diff < minute) {
        strTimeAgo = Math.floor(diff / second) + " seconds ago";
      }
      else if (diff < minute * 2) {
        strTimeAgo = "about 1 minute ago";
      }
      else if (diff < hour) {
        strTimeAgo = Math.floor(diff / minute) + " minutes ago";
      }
      else if (diff < hour * 2) {
        strTimeAgo = "about 1 hour ago";
      }
      else if (diff < day) {
        strTimeAgo =  Math.floor(diff / hour) + " hours ago";
      }
      else if (diff > day && diff < day * 2) {
        strTimeAgo = "yesterday";
      }
      else if (diff < day * 365) {
        strTimeAgo = Math.floor(diff / day) + " days ago";
      }
      else {
        strTimeAgo = "over a year ago";
      }
		return strTimeAgo;
    },
	formatTweet: function(jsonStatus)
	{
	    var strTweet = jsonStatus.text;
	    var tempURL;
	
	    for(var i=0; i < jsonStatus.entities.urls.length; i++)
	    {
	      var URL = jsonStatus.entities.urls[i];
	      tempURL = "<a target='_blank' rel='nofollow' target='_blank' href='" + URL.url + "'>" + URL.url + "</a>";
	
	      strTweet = strTweet.replace(URL.url, tempURL);
	    }
	    for(var i=0; i < jsonStatus.entities.hashtags.length; i++)
	    {
	      var Tag = jsonStatus.entities.hashtags[i];
	      tempURL = "<a target='_blank' rel='nofollow' target='_blank' href='http://twitter.com/#!/search?q=" + Tag.text + "'>#" + Tag.text + "</a>";
	
	      strTweet = strTweet.replace("#" + Tag.text, tempURL);
	    }
	
	    for(var i=0; i < jsonStatus.entities.user_mentions.length; i++)
	    {
	      var UM = jsonStatus.entities.user_mentions[i];
	      tempURL = "<a target='_blank' rel='nofollow' target='_blank' href='http://twitter.com/" + UM.screen_name+ "'>@" + UM.screen_name+ "</a>";
	
	      strTweet = strTweet.replace("@" + UM.screen_name, tempURL);
	    }
	    return strTweet;
	}
}